package qqsdk

import (
	"crypto/tls"
	"fmt"
	"net/http"
	"net/url"
	"time"

	"github.com/gorilla/websocket"
)

type WebSocketClient struct {
	conn      *websocket.Conn
	send      chan []byte
	receive   chan []byte
	onClose   func()
	onMessage func([]byte)
	onError   func(error)
	onConnect func()
}

func NewWebSocketClient() *WebSocketClient {
	return &WebSocketClient{
		send:    make(chan []byte),
		receive: make(chan []byte),
	}
}

func (c *WebSocketClient) Connect(serverURL string) error {
	u, err := url.Parse(serverURL)
	if err != nil {
		return err
	}

	dialer := &websocket.Dialer{
		Proxy:            http.ProxyFromEnvironment,
		HandshakeTimeout: 45 * time.Second,
		TLSClientConfig: &tls.Config{
			InsecureSkipVerify: true, // 忽略证书验证
		},
	}

	conn, _, err := dialer.Dial(u.String(), nil)
	if err != nil {
		return err
	}

	c.conn = conn

	if c.onConnect != nil {
		c.onConnect()
	}

	return nil
}

func (c *WebSocketClient) Close() error {
	if c.conn != nil {
		err := c.conn.Close()
		if err != nil {
			return err
		}
		if c.onClose != nil {
			c.onClose()
		}
	}
	return nil
}

func (c *WebSocketClient) Read() {
	defer c.Close()

	for {
		_, message, err := c.conn.ReadMessage()
		if err != nil {
			if c.onError != nil {
				c.onError(err)
			}
			return
		}
		c.receive <- message
	}
}

func (c *WebSocketClient) Write(message []byte) error {
	if c.conn != nil {
		select {
		case c.send <- message:
		default:
			//log.Println("Send buffer full. Dropping message:", message)
		}
		return nil
	}
	return fmt.Errorf("connection not established")
}

func (c *WebSocketClient) SetOnConnect(handler func()) {
	c.onConnect = handler
}

func (c *WebSocketClient) SetOnMessage(handler func([]byte)) {
	c.onMessage = handler
}

func (c *WebSocketClient) SetOnError(handler func(error)) {
	c.onError = handler
}

func (c *WebSocketClient) Start() {
	go c.Read()

	for {
		select {
		case message, ok := <-c.send:
			if !ok {
				return
			}
			err := c.conn.WriteMessage(websocket.TextMessage, message)
			if err != nil {
				if c.onError != nil {
					c.onError(err)
				}
				return
			}
		case message, ok := <-c.receive:
			if !ok {
				return
			}
			if c.onMessage != nil {
				go c.onMessage(message) // 在新的协程中处理消息
			}
		}
	}
}
